package com.yuntsg.ruiijn.controller.search;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.util.PoitlIOUtils;
import com.yuntsg.nnsfcp.common.utils.RedisUtil;
import com.yuntsg.nnsfcp.common.utils.UserUtil;
import com.yuntsg.ruiijn.databse_search.entity.FileRecord;
import com.yuntsg.ruiijn.databse_search.entity.ReportRecord;
import com.yuntsg.ruiijn.databse_search.entity.ReportRecordArr;
import com.yuntsg.ruiijn.databse_search.service.FileDetailService;
import com.yuntsg.ruiijn.databse_search.service.FileRecordsService;
import com.yuntsg.ruiijn.databse_search.service.ReportRecordArrService;
import com.yuntsg.ruiijn.databse_search.service.ReportRecordService;
import common.bean.R;
import common.util.AesEncryptUtils;
import common.util.CentralRequestUtil;
import common.util.MinioUtil;
import com.yuntsg.nnsfcp.common.utils.RedisUtil;
import common.vo.Scenario;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import sun.misc.BASE64Decoder;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.*;
import java.util.function.BiFunction;

@Controller
@RequestMapping("manager/pub/report")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@SuppressWarnings("all")
@Slf4j
public class ReportController {

    private final FileDetailService fileDetailService;

    private final FileRecordsService fileRecordsService;

    private final ReportRecordService reportRecordService;

    private final ReportRecordArrService reportRecordArrService;

    private final MinioUtil minioUtil;

    private final RedisUtil redisUtil;

    @Resource
    UserUtil userUtil;

    private final CentralRequestUtil requestUtil;

    BiFunction<BufferedImage, Double, Double> getheight = (b, d) -> {
        double scaleFactor = (double) b.getWidth() / (double) d;
        return b.getHeight() / scaleFactor;
    };


    /**
     * 加入报告
     */
    @RequestMapping("add")
    @ResponseBody
    public R add(@RequestBody ReportRecord record) {
        String linePath = RandomUtil.randomString(10) + ".jpg";
        FileRecord fileRecord = fileRecordsService.getById(record.getRid());

        if (null != fileRecord.getPmut() && fileRecord.getPmut().length() > 5) {
            try {
                String s = HttpUtil.get(StrUtil.format("https://pm.yuntsg.com/utils/getpuinfotong?type=1&q={}", fileRecord.getPmut()));
                JSONObject jsonObject = JSONObject.parseObject(s);
                record.setTargetInfo(jsonObject.getString("data"));
                record.setOriginInfo(jsonObject.getString("data"));
            } catch (Exception e) {
                log.info("获取论文论文信息失败");
            }
        }

        if (!StrUtil.isEmpty(record.getLinePath())) {
//            byte[] b1 = requestUtil.fetchlinePath(record.getLinePath());
            byte[] b1 = (byte[]) redisUtil.getObject(record.getLinePath());
            if (null != b1) {
                InputStream in = new ByteArrayInputStream(b1);
                String lin_path = minioUtil.upload(in, userUtil.getUid(), DateUtil.today(), "linePath_" + linePath, Scenario.view);
                record.setLinePath(lin_path);
            }

        }


        try {
            String s = HttpUtil.get(StrUtil.format("https://pm.yuntsg.com/utils/getpuinfotong?type=1&q={}", AesEncryptUtils.decrypt(record.getTpm())));
            JSONObject jsonObject = JSONObject.parseObject(s);
            record.setTargetInfo(jsonObject.getString("data"));
        } catch (Exception e) {
            log.info("获取论文论文信息失败");
        }

        if (null != record.getLinePathBase64() && StrUtil.isNotEmpty(record.getLinePathBase64())) {
            ByteArrayInputStream stream = null;
            try {
                BASE64Decoder decoder = new BASE64Decoder();
                byte[] bt = decoder.decodeBuffer(StrUtil.subAfter(record.getLinePathBase64(), "base64,", true));
                stream = new ByteArrayInputStream(bt);
            } catch (Exception e) {
                e.printStackTrace();
            }
            String lin_path = minioUtil.upload(stream, userUtil.getUid(), DateUtil.today(), "linePath_" + linePath, Scenario.view);
            record.setLinePath(lin_path);
        }

        if (null != record.getOriginFPath() && StrUtil.isNotEmpty(record.getOriginFPath())) {
            ByteArrayInputStream stream = null;
            try {
                BASE64Decoder decoder = new BASE64Decoder();
                byte[] bt = decoder.decodeBuffer(StrUtil.subAfter(record.getOriginFPath(), "base64,", true));
                stream = new ByteArrayInputStream(bt);
            } catch (Exception e) {
                e.printStackTrace();
            }
            String lin_path = minioUtil.upload(stream, userUtil.getUid(), DateUtil.today(), "ofPath_" + linePath, Scenario.view);
            record.setOriginFPath(lin_path);
        }

        if (null != record.getTargetFPath() && StrUtil.isNotEmpty(record.getTargetFPath())) {
            ByteArrayInputStream stream = null;
            try {
                BASE64Decoder decoder = new BASE64Decoder();
                byte[] bt = decoder.decodeBuffer(StrUtil.subAfter(record.getTargetFPath(), "base64,", true));
                stream = new ByteArrayInputStream(bt);
            } catch (Exception e) {
                e.printStackTrace();
            }
            String lin_path = minioUtil.upload(stream, userUtil.getUid(), DateUtil.today(), "tfPath_" + linePath, Scenario.view);
            record.setTargetFPath(lin_path);
        }

        return R.ok().put("data", reportRecordService.saveOrUpdate(record));
    }

    /**
     * 删除报告
     */
    @RequestMapping("delete")
    @ResponseBody
    public R delete(@RequestParam(value = "ids[]") String[] ids) {
        return R.ok().put("data", reportRecordService.removeByIds(Arrays.asList(ids)));
    }

    /**
     * 删除报告
     */
    @RequestMapping("update")
    @ResponseBody
    public R update(@RequestBody ReportRecord record) {
        return R.ok().put("data", reportRecordService.saveOrUpdate(record));
    }

    /**
     * 获取报告列表
     */
    @RequestMapping("list")
    @ResponseBody
    public R list(@RequestParam("rid") Integer rid) {
        return R.ok().put("data", reportRecordService.list(Wrappers.<ReportRecord>lambdaQuery().eq(ReportRecord::getRid, rid)));
    }

    /**
     * 导出报告
     */
    @RequestMapping("export")
    @ResponseBody
    public void list(@RequestParam("ids[]") Integer[] ids, @RequestParam("rid") Integer rid, @RequestParam("type") Integer type, HttpServletResponse response) throws IOException {

        FileRecord fileRecord = fileRecordsService.getById(rid);
        ReportRecordArr reportRecordArr = new ReportRecordArr();
        reportRecordArr.setRid(rid);
        reportRecordArr.setTitle(Optional.ofNullable(fileRecord.getTitle()).orElse(""));
        reportRecordArr.setAuthor(Optional.ofNullable(fileRecord.getAuthor()).orElse(""));
        reportRecordArr.setDetectionId(RandomUtil.randomInt(10000000, 99999999));
        reportRecordArr.setDetectionTime(System.currentTimeMillis());

        if (type == 0) {
            reportRecordArrService.saveOrUpdate(reportRecordArr);
            try (ServletOutputStream out = response.getOutputStream();
                 BufferedOutputStream bos = new BufferedOutputStream(out);
                 XWPFTemplate template = XWPFTemplate.compile("/data/analysis/temprate-0.docx")
                         .render(MapUtil.builder(new HashMap<String, Object>())
                                 .put("md5", fileRecord.getMd5())
                                 .put("title", reportRecordArr.getTitle())
                                 .put("author", reportRecordArr.getAuthor())
                                 .put("detectionId", reportRecordArr.getDetectionId())
                                 .put("detectionTime", DateUtil.now())
                                 .build());
            ) {
                String filename = DateUtil.format(new Date(), "yyyyMMddHHmmss") + ".docx";
                response.setContentType("application/octet-stream");
                response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
                template.write(bos);
                bos.flush();
                out.flush();
                PoitlIOUtils.closeQuietlyMulti(template, bos, out);
            } catch (Exception e) {
                e.printStackTrace();
                log.info("导出报告失败");
            }
        } else {
            reportRecordArrService.saveOrUpdate(reportRecordArr.setArr(Arrays.asList(ids)));
            List<ReportRecord> list = reportRecordService.listByIds(Arrays.asList(ids));

            List<Map<String, Object>> data = new ArrayList<>();
            int index = 1;
            for (ReportRecord reportRecord : list) {
                Map<String, Object> map = new HashMap<>();
                map.put("similarity", reportRecord.getSimilarity());
                map.put("originInfo", Optional.ofNullable(reportRecord.getOriginInfo()).orElse(" "));
                map.put("targetInfo", Optional.ofNullable(reportRecord.getTargetInfo()).orElse(" "));

                BufferedImage originPath = minioUtil.fetchImage(reportRecord.getOriginPath());
                map.put("originPath", Pictures.ofBytes(minioUtil.downloadByte(reportRecord.getOriginPath())).sizeInCm(8.94, (double) getheight.apply(originPath, 8.94)).center().altMeta("图片不存在").create());

                BufferedImage targetPath = minioUtil.fetchImage(reportRecord.getTargetPath());
                map.put("targetPath", Pictures.ofBytes(minioUtil.downloadByte(reportRecord.getTargetPath())).sizeInCm(8.94, (double) getheight.apply(targetPath, 8.94)).center().altMeta("图片不存在").create());

                BufferedImage originFPath = minioUtil.fetchImage(reportRecord.getOriginFPath());
                map.put("originFPath", Pictures.ofBytes(minioUtil.downloadByte(reportRecord.getOriginFPath())).sizeInCm(8.94, (double) getheight.apply(originFPath, 8.94)).center().altMeta("图片不存在").create());

                BufferedImage targetFPath = minioUtil.fetchImage(reportRecord.getTargetFPath());
                map.put("targetFPath", Pictures.ofBytes(minioUtil.downloadByte(reportRecord.getTargetFPath())).sizeInCm(8.94, (double) getheight.apply(targetFPath, 8.94)).center().altMeta("图片不存在").create());

                if (!StrUtil.isEmpty(reportRecord.getLinePath())) {
                    BufferedImage linepath = minioUtil.fetchImage(reportRecord.getLinePath());
                    map.put("linePath", Pictures.ofBytes(minioUtil.downloadByte(reportRecord.getLinePath())).sizeInCm(17.88, (double) getheight.apply(linepath, 17.88)).center().altMeta("图片不存在").create());
                }
                map.put("index", index);
                index++;
                data.add(map);
            }


            try (ServletOutputStream out = response.getOutputStream();
                 BufferedOutputStream bos = new BufferedOutputStream(out);
                 XWPFTemplate template = XWPFTemplate.compile("/data/analysis/temprate-1.docx")
                         .render(MapUtil.builder(new HashMap<String, Object>())
                                 .put("md5", fileRecord.getMd5())
                                 .put("title", reportRecordArr.getTitle())
                                 .put("author", reportRecordArr.getAuthor())
                                 .put("detectionId", reportRecordArr.getDetectionId())
                                 .put("detectionTime", DateUtil.now())
                                 .put("list", data).build());
            ) {
                String filename = DateUtil.format(new Date(), "yyyyMMddHHmmss") + ".docx";
                response.setContentType("application/octet-stream");
                response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
                template.write(bos);
                bos.flush();
                out.flush();
                PoitlIOUtils.closeQuietlyMulti(template, bos, out);

            } catch (Exception e) {
                e.printStackTrace();
                log.info("导出报告失败");
            }
        }
    }


}
